//MountManager - the program for easy mounting of storage devices in Linux
//Copyright (C) 2007-2008 Tikhonov Sergey
//
//This file is part of MountManager Gui
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#include <QtGui/QLabel>
#include <QtGui/QGridLayout>
#include <QtGui/QPushButton>
#include <QtGui/QCheckBox>
#include <QtGui/QSpinBox>
#include <QtGui/QScrollArea>
#include "../core/diskoptionsparser.h"
#include "../core/diskdevice.h"
#include "infobutton.h"
#include "specialcomboboxwidgets.h"
#include "permissionswidget.h"
#include "optionsview.h"


OptionsView::OptionsView(DiskDevice *dev,PopupWindow *popupWindow) {
	popup = popupWindow;
	device = dev;
	
	generalOptionsLayout = new QGridLayout;
	generalOptionsLayout->setColumnStretch(2,1);
	
	generalOptionsWidget = new QScrollArea;
	QWidget *tempGeneralOptionsWidget = new QWidget;
	tempGeneralOptionsWidget->setLayout(generalOptionsLayout);
	generalOptionsWidget->setWidget(tempGeneralOptionsWidget);
	generalOptionsWidget->setWidgetResizable(true);
	
	advancedOptionsWidget = new QScrollArea;
	advancedOptionsLayout = new QGridLayout;
	advancedOptionsLayout->setColumnStretch(2,1);
	QWidget *tempAdvancedOptionsWidget = new QWidget;
	tempAdvancedOptionsWidget->setLayout(advancedOptionsLayout);
	advancedOptionsWidget->setWidget(tempAdvancedOptionsWidget);
	advancedOptionsWidget->setWidgetResizable(true);
	
	udfOptionsWidget = 0;
	if (device->isSupportDvd()) {
		udfOptionsWidget = new QScrollArea;
		udfOptionsLayout = new QGridLayout;
		udfOptionsLayout->setColumnStretch(2,1);
		QWidget *tempUdfOptionsWidget = new QWidget;
		tempUdfOptionsWidget->setLayout(udfOptionsLayout);
		udfOptionsWidget->setWidget(tempUdfOptionsWidget);
		udfOptionsWidget->setWidgetResizable(true);
	}
		
	if (device->fileSystem() == "ntfs" || device->fileSystem() == "ntfs-3g") {
		ntfs3gOptionsWidget = new QScrollArea;
		ntfs3gOptionsLayout = new QGridLayout;
		ntfs3gOptionsLayout->setColumnStretch(2,1);
		QWidget *tempNtfs3gOptionsWidget = new QWidget;
		tempNtfs3gOptionsWidget->setLayout(ntfs3gOptionsLayout);
		ntfs3gOptionsWidget->setWidget(tempNtfs3gOptionsWidget);
		ntfs3gOptionsWidget->setWidgetResizable(true);
	}
	else {
		ntfs3gOptionsWidget = 0;
		ntfs3gOptionsLayout = 0;
	}
	showOptions(QList<int>() << General << Advanced);
}

OptionsView::~OptionsView() {
	delete generalOptionsWidget;
	delete advancedOptionsWidget;
	if (ntfs3gOptionsWidget)
		delete ntfs3gOptionsWidget;
	if (udfOptionsWidget)
		delete udfOptionsWidget;
}

void OptionsView::addOptions(const QList<Option *>& opts,const QString& source) {
	foreach (Option *option,opts) {
		if (option->optionType == "CheckBox")
			addCheckBoxOption(option,source);
		else if (option->optionType == "ComboBox" || option->optionType == "Encoding"
				|| option->optionType == "Codepage" || option->optionType == "GID"
				|| option->optionType == "UID" || option->optionType == "Locale")
			addComboBoxOption(option,source);
		else if (option->optionType == "Permissions")
			addPermOption(option,source);
		else if (option->optionType == "SpinBox")
			addSpinBoxOption(option,source);
	}
	if (source == "common")
		generalOptionsLayout->setRowStretch(generalOptionsLayout->rowCount(),1);
	else if (source == "ntfs-3g")
		ntfs3gOptionsLayout->setRowStretch(ntfs3gOptionsLayout->rowCount(),1);
	else if (source == "udf")
		udfOptionsLayout->setRowStretch(udfOptionsLayout->rowCount(),1);
	else
		advancedOptionsLayout->setRowStretch(advancedOptionsLayout->rowCount(),1);
}

void OptionsView::addCheckBoxOption(Option *option,const QString& source) {
	QCheckBox *checkBox = new QCheckBox(option->optionTitle);
	connect(checkBox,SIGNAL(clicked()),this,SIGNAL(optionChanged()));

	if (option->optionValues.count() == 2)
		foreach (Value *value,option->optionValues)
			if (value->isDefault && value->isChecked) {
				checkBox->setChecked(true);
				break;
			}
	foreach (QString fstabOption, device->fstabOptions().split(","))
		foreach (Value *value, option->optionValues)
			if (value->text == fstabOption) {
				if (option->optionValues.count() == 2) {
					if (!value->isDefault)
						checkBox->setChecked(!checkBox->isChecked());
				} else
					checkBox->setChecked(true);
			}
	
	QGridLayout *layout = 0;
	if (source == "common")
		layout = generalOptionsLayout;
	else if (source == "ntfs-3g")
		layout = ntfs3gOptionsLayout;
	else if (source == "udf")
		layout = udfOptionsLayout;
	else
		layout = advancedOptionsLayout;

	InfoButton *infoButton = 0;
	if (!option->optionDocMark.isEmpty())
		infoButton = new InfoButton(popup);
	int row = layout->rowCount()+1;
	layout->addWidget(infoButton,row,0);
	layout->addWidget(checkBox,row,1,1,2);

	OptionView *optionView = new OptionView;
	optionView->type = CheckBox;
	optionView->checkBox = checkBox;
	optionView->source = source;
	optionView->option = option;
	
	options.append(optionView);
}

void OptionsView::addComboBoxOption(Option *option,const QString& source) {
	QComboBox *comboBox = 0;
	if (option->optionType == "Encoding")
		comboBox = new EncodingWidget(option->optionValues[0]->text);
	else if (option->optionType == "Codepage")
		comboBox = new CodepageWidget;
	else if (option->optionType == "GID")
		comboBox = new GIDWidget;
	else if (option->optionType == "UID")
		comboBox = new UIDWidget;
	else if (option->optionType == "Locale")
		comboBox = new LocaleWidget;
	else {
		comboBox = new QComboBox;
		int currentIndex = 0;
		foreach (Value *value, option->optionValues) {
			comboBox->addItem(option->optionComboBoxItems[currentIndex],value->text);
			currentIndex++;
		}
	}
	connect(comboBox,SIGNAL(currentIndexChanged(int)),this,SIGNAL(optionChanged()));

	if (!device->fstabOptions().isEmpty())
		for (int i = 0; i < comboBox->count(); i++) {
			foreach (QString fstabOption,device->fstabOptions().split(","))
				if (fstabOption == comboBox->itemData(i).toString()) {
					comboBox->setCurrentIndex(i);
					goto exitFromCicle;
				}
			exitFromCicle:
				break;
		}
	
	QGridLayout *layout = 0;
	if (source == "common")
		layout = generalOptionsLayout;
	else if (source == "ntfs-3g")
		layout = ntfs3gOptionsLayout;
	else if (source == "udf")
		layout = udfOptionsLayout;
	else
		layout = advancedOptionsLayout;
		
	InfoButton *infoButton = 0;
	if (!option->optionDocMark.isEmpty())
		infoButton = new InfoButton(popup);
	
	QLabel *label = new QLabel(option->optionTitle);
	
	int row = layout->rowCount()+1;
	layout->addWidget(infoButton,row,0);
	layout->addWidget(label,row,1);
	layout->addWidget(comboBox,row,2);


	OptionView *optionView = new OptionView;
	optionView->type = ComboBox;
	optionView->comboBox = comboBox;
	optionView->source = source;
	optionView->label = label;
	optionView->option = option;
	
	options.append(optionView);
}

void OptionsView::addSpinBoxOption(Option *option,const QString &source) {
	QStringList list = option->optionTitle.split("-=Type=-");
	
	QLabel *leftLabel = new QLabel(list[0]);
	QLabel *rightLabel = new QLabel(list[1]);
	QSpinBox *spinBox = new QSpinBox;
	spinBox->setMaximum(10000);
	connect(spinBox,SIGNAL(valueChanged(int)),this,SIGNAL(optionChanged()));

	if (!option->optionDefaultValue.isEmpty())
		spinBox->setValue(QVariant(option->optionDefaultValue).toInt());
	foreach (QString fstabOption, device->fstabOptions().split(",")) {
		QStringList optionList = fstabOption.split("=");
		if (optionList.count() != 2)
			continue;
		if (option->optionValues[0]->text == optionList[0] + "=")
			spinBox->setValue(QVariant(optionList[1]).toInt());
	}
	
	QGridLayout *layout = 0;
	if (source == "common")
		layout = generalOptionsLayout;
	else if (source == "ntfs-3g")
		layout = ntfs3gOptionsLayout;
	else if (source == "udf")
		layout = udfOptionsLayout;
	else
		layout = advancedOptionsLayout;
	
	InfoButton *infoButton = 0;
	if (!option->optionDocMark.isEmpty())
		infoButton = new InfoButton(popup);

	QWidget *spinBoxWidget = new QWidget;
	QHBoxLayout *spinBoxLayout = new QHBoxLayout;
	spinBoxLayout->addWidget(leftLabel);
	spinBoxLayout->addWidget(spinBox);
	spinBoxLayout->addWidget(rightLabel);
	spinBoxWidget->setLayout(spinBoxLayout);

	int row = layout->rowCount()+1;
	layout->addWidget(infoButton,row,0);
	layout->addWidget(spinBoxWidget,row,1,1,2);

	OptionView *optionView = new OptionView;
	optionView->type = SpinBox;
	optionView->spinBox = spinBox;
	optionView->source = source;
	optionView->label = leftLabel;
	optionView->extraLabel = rightLabel;
	optionView->option = option;
	
	options.append(optionView);
}

void OptionsView::addPermOption(Option *option,const QString &source) {
	PermissionsWidget *permWidget = new PermissionsWidget(option);
	connect(permWidget,SIGNAL(permissionsChanged()),this,SIGNAL(optionChanged()));

	foreach (QString fstabOption,device->fstabOptions().split(","))
		if (fstabOption.contains(option->optionValues[0]->text))
			permWidget->setCode(fstabOption.replace(option->optionValues[0]->text,""));
	
	QGridLayout *layout = 0;
	if (source == "common")
		layout = generalOptionsLayout;
	else if (source == "ntfs-3g")
		layout = ntfs3gOptionsLayout;
	else if (source == "udf")
		layout = udfOptionsLayout;
	else
		layout = advancedOptionsLayout;
	
	InfoButton *infoButton = 0;
	if (!option->optionDocMark.isEmpty())
		infoButton = new InfoButton(popup);
	
	int row = layout->rowCount()+1;
	layout->addWidget(infoButton,row,0);
	layout->addWidget(permWidget,row,1,1,2);

	OptionView *optionView = new OptionView;
	optionView->type = Perm;
	optionView->permWidget = permWidget;
	optionView->source = source;
	optionView->option = option;
	
	options.append(optionView);
}

QString OptionsView::getOptions(bool includeDefaultOptions) {
	QString optionsString;

	foreach (OptionView *optionView,options) {
		bool toContinue = false;
		foreach (int type,shownTabs) {
			if ((type == Ntfs3g && optionView->source == "ntfs-3g")
				|| (type == Udf && (optionView->source == "udf" || optionView->source == "common"))
				|| (type == Iso && (optionView->source == "iso9660" || optionView->source == "common"))
				|| (type == General && optionView->source == "common") 
				|| (type == Advanced && optionView->source == device->fileSystem())
			) {
				toContinue = true;
				break;
			}
		}
		if (!toContinue)
			continue;
		
		switch (optionView->type) {
			case CheckBox:
				if (optionView->option->optionValues.count() == 1) {
					if (optionView->checkBox->isChecked())
						optionsString += "," + optionView->option->optionValues[0]->text;
				} else {
					if (optionView->checkBox->isChecked()) {
						QString defaultValue;
						QString checkedValue;
						foreach (Value *value,optionView->option->optionValues) {
							if (value->isDefault)
								defaultValue = value->text;
							if (value->isChecked)
								checkedValue = value->text;
						}
						if ((defaultValue == checkedValue && includeDefaultOptions) || defaultValue != checkedValue)
							optionsString += "," + checkedValue;
					}
					else {
						foreach (Value *value,optionView->option->optionValues)
							if (!value->isChecked) {
								if ((value->isDefault && includeDefaultOptions) || !value->isDefault)
									optionsString += "," + value->text;
							}
					}
				}
				break;
			case ComboBox:
				if (optionView->comboBox->currentIndex() != 0 || includeDefaultOptions)
					optionsString += ',' + optionView->comboBox->itemData(optionView->comboBox->currentIndex()).toString();
				break;
			case SpinBox:
				if (includeDefaultOptions || optionView->option->optionDefaultValue != QVariant(optionView->spinBox->value()).toString())
					optionsString += "," + optionView->option->optionValues[0]->text + QVariant(optionView->spinBox->value()).toString();
				break;
			case Perm:
				if (includeDefaultOptions || !optionView->permWidget->isDefaultValue())
					optionsString += "," + optionView->permWidget->codeForFstab();
				break;
		}
	}
	
	if (!optionsString.isEmpty())
		optionsString.remove(0,1);
	return optionsString;
}

void OptionsView::showOptions(QList<int> types) {
	clear();
	shownTabs.clear();
	foreach (int type,types) {
		if (type == General && generalOptionsWidget)
			addTab(generalOptionsWidget,tr("General"));
		else if (type == Advanced && advancedOptionsWidget)
			addTab(advancedOptionsWidget,tr("Advanced"));
		else if (type == Ntfs3g && ntfs3gOptionsWidget)
			addTab(ntfs3gOptionsWidget,tr("Ntfs-3g options"));
		else if (type == Udf && udfOptionsWidget)
			addTab(udfOptionsWidget,tr("DVD options"));
		else if (type == Iso && advancedOptionsWidget)
			addTab(advancedOptionsWidget,tr("CD options"));
	}
	shownTabs = types;
}
